package cn.mjnxin.iot.gate.handle;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.List;

import cn.mjnxin.iot.base.domain.ChannelData;
import cn.mjnxin.iot.base.log.LogWorker;
import cn.mjnxin.iot.base.util.CommonUtil;
import cn.mjnxin.iot.gate.cache.GateRuntimeCache;
import cn.mjnxin.iot.gate.worker.Gate2TerminalWorker;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;

/**
 * 接收终端报文转发前置
 * @author CLG 2023年10月10日
 * @version V1.0.0
 */
@Sharable
public class GateAsServer4HostInHandler extends ChannelInboundHandlerAdapter{
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        if(msg instanceof List){
            @SuppressWarnings("unchecked")
            List<ChannelData> dataList = (List<ChannelData>) msg;
            
            for (ChannelData channelData : dataList) {
            	Gate2TerminalWorker.getInstance().add(channelData);
            }
            
        } else{
            ChannelData channelData = (ChannelData)msg;
            Gate2TerminalWorker.getInstance().add(channelData);
//          analyse();
        }
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);
        InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
        if (insocket != null) {
            String hostKey = CommonUtil.getIpAddress(insocket);
            GateRuntimeCache.hostLink(hostKey, ctx.channel());
        }
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
    	System.err.println("GateAsServer4Host.channelInactive(ChannelHandlerContext ctx)");
        super.channelInactive(ctx);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
    	System.err.println("GateAsServer4Host.exceptionCaught(ChannelHandlerContext ctx, Throwable cause)");
        Channel channel = ctx.channel();
        InetSocketAddress insocket = (InetSocketAddress)channel.remoteAddress();
        if (cause instanceof IOException || cause instanceof OutOfMemoryError) {
            LogWorker.logForce(String.format("Host[%s]断连", insocket.toString()));
            if (insocket != null) {
                String hostKey = CommonUtil.getIpAddress(insocket);
                /**
                 * 发生异常时删除缓存中对应的terminal的缓存
                 */
                GateRuntimeCache.hostUnlink(hostKey);
            }
        } else {
            LogWorker.logForce(String.format("Host[%s]其他异常", insocket.toString()));
        }
        super.exceptionCaught(ctx, cause);
    }
    
    /**
     * 心跳检测触发的事件通过本方法捕获
     */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
    	System.err.println("GateAsServer4Host.userEventTriggered(ChannelHandlerContext ctx, Object evt)" + evt);
        if (evt instanceof IdleStateEvent) {
            IdleState state = ((IdleStateEvent) evt).state();
            // 超时无读写事件，自动断连
            if(state == IdleState.READER_IDLE ){
                ChannelFuture fcutrue =  ctx.close();
                fcutrue.addListener(new ChannelFutureListener() {
                    public void operationComplete(ChannelFuture future) throws Exception {
                        Channel channel = future.channel();
                        InetSocketAddress insocket = (InetSocketAddress)channel.remoteAddress();
                        String ipAddress = CommonUtil.getIpAddress(insocket);
                        LogWorker.logForce(String.format("Host[%s]心跳超时下线成功....", ipAddress));
                        if (insocket != null) {
                            String hostKey = CommonUtil.getIpAddress(insocket);
                            /**
                             * 发生异常时删除缓存中对应的所有terminal的缓存
                             */
                            GateRuntimeCache.hostUnlink(hostKey);
                        }
                        channel.close();
                    }
                });
            }
        }else{  
            super.userEventTriggered(ctx, evt);
        }
    }
}
